﻿using System.IO.Ports;
using System.Windows;
using System.Windows.Controls;

namespace Xioa_UI.Controls;

public class XioaRs232Border : ContentControl, IDisposable
{
    #region Static Helper

    public static IEnumerable<string> GetPorts()
    {
        return SerialPort.GetPortNames();
    }

    #endregion

    #region Field

    private SerialPort? _serialPort;
    private bool _isOpen = false;

    #endregion

    #region Property
    public int DataBits
    {
        get { return (int)GetValue(DataBitsProperty); }
        set { SetValue(DataBitsProperty, value); }
    }
    public string PortName
    {
        get { return (string)GetValue(PortNameProperty); }
        set { SetValue(PortNameProperty, value); }
    }
    public StopBits StopBits
    {
        get { return (StopBits)GetValue(StopBitsProperty); }
        set { SetValue(StopBitsProperty, value); }
    }
    public int BaudRate
    {
        get { return (int)GetValue(BaudRateProperty); }
        set { SetValue(BaudRateProperty, value); }
    }
    public Parity Parity
    {
        get { return (Parity)GetValue(ParityProperty); }
        set { SetValue(ParityProperty, value); }
    }
    public int ReadTimeout
    {
        get { return (int)GetValue(ReadTimeoutProperty); }
        set { SetValue(ReadTimeoutProperty, value); }
    }
    public Handshake Handshake
    {
        get { return (Handshake)GetValue(HandshakeProperty); }
        set { SetValue(HandshakeProperty, value); }
    }
    public int WriteTimeout
    {
        get { return (int)GetValue(WriteTimeoutProperty); }
        set { SetValue(WriteTimeoutProperty, value); }
    }

    #endregion

    #region DependencyProperty

    /// <summary>
    /// 获取数据位
    /// </summary>
    public static readonly DependencyProperty DataBitsProperty =
        ElementBase.Property<XioaRs232Border, int>("DataBitsProperty", 8);

    /// <summary>
    /// 串口的名称
    /// </summary>
    public static readonly DependencyProperty PortNameProperty =
        ElementBase.Property<XioaRs232Border, string>("PortNameProperty", "");

    /// <summary>
    /// 获取停止位
    /// </summary>
    public static readonly DependencyProperty StopBitsProperty =
       ElementBase.Property<XioaRs232Border, StopBits>("StopBitsProperty", StopBits.One);

    /// <summary>
    /// 串口的波特率
    /// </summary>
    public static readonly DependencyProperty BaudRateProperty =
      ElementBase.Property<XioaRs232Border, int>("BaudRateProperty", 9600);

    /// <summary>
    /// 奇偶校验位
    /// </summary>
    public static readonly DependencyProperty ParityProperty =
       ElementBase.Property<XioaRs232Border, Parity>("ParityProperty", Parity.None);

    /// <summary>
    /// 获取读取超时时间
    /// </summary>
    public static readonly DependencyProperty ReadTimeoutProperty =
       ElementBase.Property<XioaRs232Border, int>("ReadTimeoutProperty", 2000);

    /// <summary>
    /// 获取握手模式
    /// </summary>
    public static readonly DependencyProperty HandshakeProperty =
       ElementBase.Property<XioaRs232Border, Handshake>("HandshakeProperty", Handshake.None);

    /// <summary>
    /// 写入超时时间
    /// </summary>
    public static readonly DependencyProperty WriteTimeoutProperty =
        ElementBase.Property<XioaRs232Border, int>("WriteTimeoutProperty", 2000);

    #endregion

    #region Initialize

    public void Initialize(string token)
    {
        _serialPort?.Close();
        _serialPort = new SerialPort()
        {
            DataBits = this.DataBits,
            PortName = this.PortName,
            StopBits = this.StopBits,
            BaudRate = this.BaudRate,
            Parity = this.Parity,
            ReadTimeout = this.ReadTimeout,
            Handshake = this.Handshake,
            WriteTimeout = this.WriteTimeout,
        };
    }

    #endregion

    #region Open

    public void Open()
    {
        if (_serialPort is null)
            throw new Exception("Please Use Initialize Method !");
        if (_isOpen)
            throw new Exception("SerialPort Already Is Open !");

        _serialPort.Open(); // 打开串口

        _isOpen = _serialPort.IsOpen;
    }

    #endregion

    #region Write

    public void Write(string text)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        _serialPort?.Write(text);
    }

    public void Write(byte[] buffer, int offset, int count)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        _serialPort?.Write(buffer, offset, count);
    }

    public void Write(char[] buffer, int offset, int count)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        _serialPort?.Write(buffer, offset, count);
    }

    public void WriteLine(string text)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        _serialPort?.WriteLine(text);
    }

    #endregion

    #region Read

    public int Read(byte[] buffer, int offset, int count)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.Read(buffer, offset, count);
    }

    public int Read(char[] buffer, int offset, int count)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.Read(buffer, offset, count);
    }

    public int ReadByte()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.ReadByte();
    }
    public int ReadChar()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.ReadChar();
    }

    public string ReadExisting()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.ReadExisting();
    }

    public string ReadLine()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.ReadLine();
    }

    public string ReadTo(string value)
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.ReadTo(value);
    }

    #endregion

    #region Bytes Length 

    public int GetBytesToRead()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        return _serialPort.BytesToRead;
    }

    #endregion

    #region Dispose In Out Buffer

    public void DiscardInBuffer()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        _serialPort.DiscardInBuffer();
    }

    public void DiscardOutBuffer()
    {
        if (!_isOpen)
            throw new Exception("SerialPort Is Not Open!, Please Use Open Method");
        if (_serialPort is null)
            throw new Exception();
        _serialPort.DiscardOutBuffer();
    }

    #endregion

    #region Dispose Close

    public void Close()
    {
        _isOpen = false;
        _serialPort?.Close();
        _serialPort = null;
    }

    public void Dispose()
    {
        _isOpen = false;
        _serialPort?.Close();
        _serialPort?.Dispose();
        _serialPort = null;
    }

    #endregion

}